package com.junhong.forum.batch;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.ejb.LocalBean;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.inject.Inject;
import javax.interceptor.ExcludeDefaultInterceptors;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import au.com.bytecode.opencsv.CSVParser;
import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.bean.ColumnPositionMappingStrategy;
import au.com.bytecode.opencsv.bean.CsvToBean;
import au.com.bytecode.opencsv.bean.HeaderColumnNameTranslateMappingStrategy;

import com.junhong.forum.batch.jaxb.CJTransactionReports;
import com.junhong.forum.batch.jaxb.Deals;
import com.junhong.forum.batch.jaxb.PepperJamTransaction;
import com.junhong.forum.batch.jaxb.SkimLinksTransactionReports;
import com.junhong.forum.common.Constants;
import com.junhong.forum.common.RecordStatus;
import com.junhong.forum.common.javabean.CJTransactionReportBean;
import com.junhong.forum.common.javabean.EbayTransactionReportBean;
import com.junhong.forum.common.javabean.LinkshareTransactionReportBean;
import com.junhong.forum.common.javabean.PepperJamTransactionReportBean;
import com.junhong.forum.common.javabean.SkimLinksTransactionReportBean;
import com.junhong.forum.entity.Affiliate;
import com.junhong.forum.entity.Store;
import com.junhong.forum.entity.ThreadStaging;
import com.junhong.forum.entity.TransactionReportStaging;
import com.junhong.forum.service.AffiliateEjb;
import com.junhong.forum.service.StoreEjb;
import com.junhong.forum.service.ThreadStagingEjb;
import com.junhong.forum.service.TransactionRecordStagingEjb;
import com.junhong.util.CommonUtil;
import com.junhong.util.EncryptionUtil;
import com.junhong.util.StringUtil;

/**
 * Session Bean implementation class PopulateStoreDealBatch
 */
@ExcludeDefaultInterceptors
@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.CONTAINER)
public class PopulateDealBatch {

	@Inject
	private StoreEjb					storeEjb;
	@Inject
	private ThreadStagingEjb			threadStagingEjb;
	@Inject
	Logger								logger;
	@Inject
	private TransactionRecordStagingEjb	tranReportStagingEjb;
	@Inject
	private AffiliateEjb				affiliateEjb;

	/**
	 * 
	 * Default constructor.
	 */
	public PopulateDealBatch() {
	}

	@Schedule(dayOfMonth = "*", month = "*", year = "*", hour = "*/2", persistent = false)
	@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public void populateStoreDeals() {
		List<Store> storeList = storeEjb.getStoreList(0, 1000);

		for (Store store : storeList) {
			processStoreDeals(store);

		}

	}

	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void processStoreDeals(Store store) {
		if (StringUtil.isNullOrBlank(store.getSourceXmlURL()) || StringUtil.isNullOrBlank(store.getTransformXSL())) {
			return;
		}
		store = storeEjb.getStoreById(store.getId());
		// String sourceXmlURL = store.getSourceXmlURL();
		List<String> sourceXmlURLS = XmlProcessor.parse(store.getSourceXmlURL());
		String xsltFileName = "dealxsl/" + store.getTransformXSL();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		InputStream inputStream = null;
		InputStream xslInputStream = null;
		try {
			// Use a Transformer for output
			// initialize transformer
			xslInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xsltFileName);
			TransformerFactory tFactory = TransformerFactory.newInstance();
			StreamSource stylesource = new StreamSource(xslInputStream);
			Transformer transformer = tFactory.newTransformer(stylesource);
			for (String sourceXmlURL : sourceXmlURLS) {
				URL sourceURL = new URL(sourceXmlURL);
				inputStream = sourceURL.openStream();
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document document = builder.parse(inputStream);
				DOMSource source = new DOMSource(document);
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				StreamResult result = new StreamResult(baos);
				transformer.transform(source, result);
				String transformedXML = baos.toString();
				populateDealIntoThreadStaging(store, transformedXML);
				// sleep for 3 second
				Thread.sleep(3000);

			}
			// store = storeEjb.findByIdWithPessimisticWrite(store.getId());
			// store.setTargetXML(transformedXML);
			// store.setLastUpdateTime(CommonUtil.getESTDate(new Date()));
			// storeEjb.updateStoreWithAuthorization(store);
		} catch (TransformerConfigurationException tce) {
			// Error generated by the parser
			System.out.println("\n** Transformer Factory error");
			System.out.println("   " + tce.getMessage());
			// Use the contained exception, if any
			Throwable x = tce;

			if (tce.getException() != null) {
				x = tce.getException();
			}

			x.printStackTrace();
		} catch (TransformerException te) {
			// Error generated by the parser
			System.out.println("\n** Transformation error");
			System.out.println("   " + te.getMessage());

			// Use the contained exception, if any
			Throwable x = te;

			if (te.getException() != null) {
				x = te.getException();
			}

			x.printStackTrace();
		} catch (SAXException sxe) {
			// Error generated by this application
			// (or a parser-initialization error)
			Exception x = sxe;

			if (sxe.getException() != null) {
				x = sxe.getException();
			}

			x.printStackTrace();
		} catch (ParserConfigurationException pce) {
			// Parser with specified options can't be built
			pce.printStackTrace();
		} catch (IOException ioe) {
			// I/O error
			ioe.printStackTrace();
		} catch (InterruptedException ex) {
			System.out.println("Interrupted Exception is thrown when populateStoreDeals");
			ex.printStackTrace();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioExp) {
					ioExp.printStackTrace();

				}
			}
			if (xslInputStream != null) {
				try {
					xslInputStream.close();
				} catch (IOException ioExp) {
					ioExp.printStackTrace();

				}
			}
		}

	}

	/**
	 * this method will be used for both store deal population and affiliate deal population 1. for Store, the store id will always there, 2 for
	 * affilaite, store is always null.
	 * 
	 * @param xmlContent
	 */
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void populateDealIntoThreadStaging(Store store, String xmlContent) {
		Deals deals = null;
		if (StringUtil.isNullOrBlank(xmlContent)) {
			return;
		}
		try {
			JAXBContext context = JAXBContext.newInstance(Deals.class);
			// get variables from our xml file, created before
			Unmarshaller um = context.createUnmarshaller();
			InputStream inputStream = new ByteArrayInputStream(xmlContent.getBytes("UTF-8"));
			deals = (Deals) um.unmarshal(new StreamSource(new StringReader(xmlContent)));
		} catch (JAXBException jaxbExp) {
			jaxbExp.printStackTrace();
		} catch (UnsupportedEncodingException jaxbExp) {
			jaxbExp.printStackTrace();
		}
		if (deals == null) {
			return;
		}
		ArrayList<ThreadStaging> list = deals.getThreads();
		if (list == null || list.isEmpty()) {
			return;
		}
		List<ThreadStaging> temp = null;
		StringBuilder content = new StringBuilder();
		Store tempStore = null;
		for (ThreadStaging threadStaging : list) {
			temp = threadStagingEjb.getThreadStagingWithoutAuthorization(threadStaging.getExternalId());
			tempStore = null;
			if (null == temp || temp.isEmpty()) {
				content.setLength(0);
				if (store != null) {
					threadStaging.setStore(store);
					if (StringUtil.isNullOrBlank(threadStaging.getThumbPicURL())) {
						threadStaging.setThumbPicURL("/resources/storePic/" + store.getStorePicturePathURL());
					}
				} else if (!StringUtil.isNullOrBlank(threadStaging.getAdvertiserId())) {
					String advertiserId = threadStaging.getAdvertiserId();
					if (!StringUtil.isNullOrBlank(advertiserId)) {
						tempStore = storeEjb.getStoreByAdvertiserId(advertiserId);
						if (null != tempStore) {
							threadStaging.setStore(tempStore);
							threadStaging.setThumbPicURL("/resources/storePic/" + tempStore.getStorePicturePathURL());
						}
					}

				}
				content.append(threadStaging.getContent());
				// append deal link in the content: not required, it should be
				// in the content itself, done by xslt;
				// content.append(threadStaging.getContent()).append("<br/><a href='").append(threadStaging.getDealURL()).append("' target='_blank'>Link</a>");

				/*
				 * check if content already have image, if yes, extract it and put it on the thumPicURL(thumPicURL is used as the main Deal picture)
				 * if no, then append it from the thumbPicURL
				 * 
				 * Assume: the Image either in the thumPicURL or in the content. Otherwise we can not display image on the hotdeals/front deals.
				 */
				String firstImgPath = getFirstPicture(threadStaging.getContent());
				if (StringUtil.isNullOrBlank(firstImgPath)) {
					content.append("<br/><img width='200' src='").append(threadStaging.getThumbPicURL()).append("'/>");

				} else {
					threadStaging.setThumbPicURL(firstImgPath);
				}
				threadStaging.setContent(content.toString());
				threadStagingEjb.createThreadStagingWithoutAuthorization(threadStaging);
			}
		}
	}

	/**
	 * retrieve xml content through ws end point or rss feed and then apply xsl to the given xml
	 * 
	 * @param sourceURLStr
	 * @param xslFileName
	 * @return
	 */
	public String retrieveAndTransform(String sourceURLStr, String xslFileName) {
		if (StringUtil.isNullOrBlank(sourceURLStr) || StringUtil.isNullOrBlank(xslFileName)) {
			return "";
		}
		String transformedXML = "";
		String xsltFileName = "dealxsl/" + xslFileName;
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		InputStream inputStream = null;
		InputStream xslInputStream = null;
		try {
			// Use a Transformer for output
			// initialize transformer
			xslInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xsltFileName);
			TransformerFactory tFactory = TransformerFactory.newInstance();
			StreamSource stylesource = new StreamSource(xslInputStream);
			Transformer transformer = tFactory.newTransformer(stylesource);
			URL sourceURL = new URL(sourceURLStr);
			inputStream = sourceURL.openStream();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse(inputStream);
			DOMSource source = new DOMSource(document);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			StreamResult result = new StreamResult(baos);
			transformer.transform(source, result);
			transformedXML = baos.toString();

		} catch (TransformerConfigurationException tce) {
			// Error generated by the parser
			System.out.println("\n** Transformer Factory error");
			System.out.println("   " + tce.getMessage());
			// Use the contained exception, if any
			Throwable x = tce;

			if (tce.getException() != null) {
				x = tce.getException();
			}

			x.printStackTrace();
		} catch (TransformerException te) {
			// Error generated by the parser
			System.out.println("\n** Transformation error");
			System.out.println("   " + te.getMessage());

			// Use the contained exception, if any
			Throwable x = te;

			if (te.getException() != null) {
				x = te.getException();
			}

			x.printStackTrace();
		} catch (SAXException sxe) {
			// Error generated by this application
			// (or a parser-initialization error)
			Exception x = sxe;

			if (sxe.getException() != null) {
				x = sxe.getException();
			}

			x.printStackTrace();
		} catch (ParserConfigurationException pce) {
			// Parser with specified options can't be built
			pce.printStackTrace();
		} catch (IOException ioe) {
			// I/O error
			ioe.printStackTrace();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioExp) {
					ioExp.printStackTrace();

				}
			}
			if (xslInputStream != null) {
				try {
					xslInputStream.close();
				} catch (IOException ioExp) {
					ioExp.printStackTrace();

				}
			}
		}
		return transformedXML;
	}

	public String retrieveAndTransform(String sourceURLStr, String xslFileName, boolean requireHeaderAuthorization, String headerName,
			String headerValue) {
		if (StringUtil.isNullOrBlank(sourceURLStr) || StringUtil.isNullOrBlank(xslFileName)) {
			return "";
		}
		String transformedXML = "";
		String xsltFileName = "dealxsl/" + xslFileName;
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		InputStream inputStream = null;
		InputStream xslInputStream = null;
		try {
			// Use a Transformer for output
			// initialize transformer
			xslInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xsltFileName);
			TransformerFactory tFactory = TransformerFactory.newInstance();
			StreamSource stylesource = new StreamSource(xslInputStream);
			Transformer transformer = tFactory.newTransformer(stylesource);

			URL sourceURL = new URL(sourceURLStr);
			if (requireHeaderAuthorization) {
				URLConnection urlConn = sourceURL.openConnection();
				// set authorization
				urlConn.setDoInput(true);
				urlConn.setRequestProperty(headerName, headerValue);

				inputStream = urlConn.getInputStream();
			} else {
				inputStream = sourceURL.openStream();
			}
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse(inputStream);
			DOMSource source = new DOMSource(document);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			StreamResult result = new StreamResult(baos);
			transformer.transform(source, result);
			transformedXML = baos.toString();

		} catch (TransformerConfigurationException tce) {
			// Error generated by the parser
			System.out.println("\n** Transformer Factory error");
			System.out.println("   " + tce.getMessage());
			// Use the contained exception, if any
			Throwable x = tce;

			if (tce.getException() != null) {
				x = tce.getException();
			}

			x.printStackTrace();
		} catch (TransformerException te) {
			// Error generated by the parser
			System.out.println("\n** Transformation error");
			System.out.println("   " + te.getMessage());

			// Use the contained exception, if any
			Throwable x = te;

			if (te.getException() != null) {
				x = te.getException();
			}

			x.printStackTrace();
		} catch (SAXException sxe) {
			// Error generated by this application
			// (or a parser-initialization error)
			Exception x = sxe;

			if (sxe.getException() != null) {
				x = sxe.getException();
			}

			x.printStackTrace();
		} catch (ParserConfigurationException pce) {
			// Parser with specified options can't be built
			pce.printStackTrace();
		} catch (IOException ioe) {
			// I/O error
			ioe.printStackTrace();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException ioExp) {
					ioExp.printStackTrace();

				}
			}
			if (xslInputStream != null) {
				try {
					xslInputStream.close();
				} catch (IOException ioExp) {
					ioExp.printStackTrace();

				}
			}
		}
		return transformedXML;
	}

	@Schedule(dayOfMonth = "*", month = "*", year = "*", hour = "*/2", persistent = false)
	@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public void populateAllAffiliateDeals() {
		List<Affiliate> affiliateList = affiliateEjb.getAllAffiliatesWithoutAuthorization();
		for (Affiliate affiliate : affiliateList) {
			processAffiliateDeals(affiliate);
		}

	}

	@Schedule(dayOfMonth = "*", month = "*", year = "*", hour = "4", persistent = false)
	@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public void populateAllAffiliateTransactionReportStaging() {
		List<Affiliate> affiliateList = affiliateEjb.getAllAffiliatesWithoutAuthorization();
		String webAppRootPath = CommonUtil.getWebApplicationRootPath();
		for (Affiliate affiliate : affiliateList) {
			getDailyTransactionReport(affiliate, webAppRootPath);
		}
	}

	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void processAffiliateDeals(Affiliate affiliate) {
		if (StringUtil.isNullOrBlank(affiliate.getPromLinkWSEndPoint()) || StringUtil.isNullOrBlank(affiliate.getTransformXSL())) {
			return;
		}
		if (affiliate.getName().equalsIgnoreCase(Constants.LINKSHARE)) {
			String sourceURLStr = affiliate.getPromLinkWSEndPoint();
			String xslFileName = affiliate.getTransformXSL();
			String transformedXml = retrieveAndTransform(sourceURLStr, xslFileName);
			populateDealIntoThreadStaging(null, transformedXml);
			// check totoal number
			String totalPagesStr = XmlProcessor.parseXmlByTagName(transformedXml, "totalPages");
			int totalPages = Integer.parseInt(totalPagesStr);
			int currentPage = 2;
			while (currentPage <= totalPages) {
				sourceURLStr = affiliate.getPromLinkWSEndPoint().replace("pagenumber=1", "pagenumber=" + currentPage);
				transformedXml = retrieveAndTransform(sourceURLStr, xslFileName);
				populateDealIntoThreadStaging(null, transformedXml);
				currentPage++;

			}

		} else if (affiliate.getName().equalsIgnoreCase(Constants.CJ)) {
			String sourceURLStr = affiliate.getPromLinkWSEndPoint();
			String xslFileName = affiliate.getTransformXSL();
			String transformedXml = retrieveAndTransform(sourceURLStr, xslFileName, true, Constants.Authorization, Constants.AuthorizationValue);
			populateDealIntoThreadStaging(null, transformedXml);
			// check totoal number
			String totalMatched = XmlProcessor.parseXmlByTagName(transformedXml, "totalMatched");
			// calculate total pages, 100/page
			int totalMatchInt = Integer.parseInt(totalMatched);
			int totalPages = totalMatchInt / 100 + (totalMatchInt % 100 > 0 ? 1 : 0);
			int currentPage = 2;
			while (currentPage <= totalPages) {
				sourceURLStr = affiliate.getPromLinkWSEndPoint().replace("page-number=1", "page-number=" + currentPage);
				transformedXml = retrieveAndTransform(sourceURLStr, xslFileName, true, Constants.Authorization, Constants.AuthorizationValue);
				populateDealIntoThreadStaging(null, transformedXml);
				currentPage++;
			}
		} else if (affiliate.getName().equalsIgnoreCase(Constants.PEPPERJAM)) {
			String sourceURLStr = affiliate.getPromLinkWSEndPoint();
			String xslFileName = affiliate.getTransformXSL();
			String transformedXml = retrieveAndTransform(sourceURLStr, xslFileName);
			populateDealIntoThreadStaging(null, transformedXml);
			// check totoal number
			String totalMatched = XmlProcessor.parseXmlByTagName(transformedXml, "totalMatched");
			// calculate total pages, 100/page
			int totalMatchInt = Integer.parseInt(totalMatched);
			int totalPages = totalMatchInt / 1500 + (totalMatchInt % 1500 > 0 ? 1 : 0);
			int currentPage = 2;
			while (currentPage <= totalPages) {
				sourceURLStr = affiliate.getPromLinkWSEndPoint().replace("page=1", "page=" + currentPage);
				transformedXml = retrieveAndTransform(sourceURLStr, xslFileName);
				populateDealIntoThreadStaging(null, transformedXml);
				currentPage++;
			}
		}

	}

	/**
	 * get the daily transaction report should be run at the end of each day.
	 * 
	 * @param affiliate
	 */
	public void getDailyTransactionReport(Affiliate affiliate, String contextPath) {
		String tranReportWSEndPointTemplate = affiliate.getTransactionReportWSEndPoint();
		if (StringUtil.isNullOrBlank(tranReportWSEndPointTemplate)) {
			return;
		}
		if (affiliate.getName().equalsIgnoreCase(Constants.LINKSHARE)) {
			try {
				Date todayDate = CommonUtil.getESTDateWithoutTime(new Date());
				Date yesterday = CommonUtil.addDay(todayDate, -1);
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("bdate=20130101",
						"bdate=" + CommonUtil.getDateStringyyyymmdd(yesterday));
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("edate=20130101",
						"edate=" + CommonUtil.getDateStringyyyymmdd(todayDate));
				URL sourceWebSite = new URL(tranReportWSEndPointTemplate);
				File destFile = new File(contextPath + Constants.TRANSACTION_REPORT_DEST_FOLDER, "linkshare_transaction_report_"
						+ CommonUtil.getDateString(yesterday) + "_" + CommonUtil.getDateString(todayDate) + ".txt");
				FileUtils.copyURLToFile(sourceWebSite, destFile, Constants.FILE_DOWNLOAD_CONNECTION_TIMEOUT, Constants.FILE_READ_TIMEOUT);
				readTabDelimitedFile4Linkshare(destFile);
			} catch (IOException ioe) {
				logger.error("Error:Not able to get Daily Transaction file ", ioe);

			} finally {
				// TODO IO is closed in the readTabDelimitedFile4Linkshare files
				// no need to close it here
			}

		} else if (affiliate.getName().equalsIgnoreCase(Constants.CJ)) {
			InputStream inputStream = null;
			try {
				Date todayDate = CommonUtil.getESTDateWithoutTime(new Date());
				Date yesterday = CommonUtil.addDay(todayDate, -1);
				Date tomorrow = CommonUtil.addDay(todayDate, 1);
				// cj, only get transaction data for yesterday and today.
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("start-date=2013-01-01",
						"start-date=" + CommonUtil.getDateStringyyyymmddDash(yesterday));
				// end-date is not included in the result
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("end-date=2013-01-01",
						"end-date=" + CommonUtil.getDateStringyyyymmddDash(tomorrow));

				URL sourceWebSite = new URL(tranReportWSEndPointTemplate);
				URLConnection urlConn = sourceWebSite.openConnection();
				// set authorization
				urlConn.setDoInput(true);
				urlConn.setRequestProperty(Constants.Authorization, Constants.AuthorizationValue);
				// TODO finish this method
				inputStream = urlConn.getInputStream();
				populateCJTransactionReport(inputStream);
			} catch (IOException ioe) {
				logger.error("Error:Not able to get Daily Transaction file ", ioe);

			} finally {
				if (inputStream != null) {
					try {
						inputStream.close();
					} catch (Exception ex) {
						ex.printStackTrace();
					}

				}
			}
		} else if (affiliate.getName().equalsIgnoreCase(Constants.PEPPERJAM)) {
			InputStream inputStream = null;
			try {
				Date todayDate = CommonUtil.getESTDateWithoutTime(new Date());
				Date yesterday = CommonUtil.addDay(todayDate, -1);
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("startDate=2013-01-01",
						"startDate=" + CommonUtil.getDateStringyyyymmddDash(yesterday));
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("endDate=2013-01-01",
						"endDate=" + CommonUtil.getDateStringyyyymmddDash(todayDate));

				URL sourceWebSite = new URL(tranReportWSEndPointTemplate);
				// TODO finish this method
				inputStream = sourceWebSite.openStream();
				populatePepperJamTransactionReport(inputStream);
			} catch (IOException ioe) {
				logger.error("Error:Not able to get Daily Transaction file ", ioe);

			} finally {
				if (inputStream != null) {
					try {
						inputStream.close();
					} catch (Exception ex) {
						ex.printStackTrace();
					}

				}

			}
		} else if (affiliate.getName().equalsIgnoreCase(Constants.EBAYPARTNERNETWORK)) {
			InputStreamReader reader = null;
			try {
				Date todayDate = CommonUtil.getESTDateWithoutTime(new Date());
				Date yesterday = CommonUtil.addDay(todayDate, -1);
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("start_date=01/01/2013",
						"start_date=" + CommonUtil.getDateStringmmddyyyySlash(yesterday));
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("end_date=01/01/2013",
						"end_date=" + CommonUtil.getDateStringmmddyyyySlash(todayDate));
				URL sourceWebSite = new URL(tranReportWSEndPointTemplate);
				File destFile = new File(contextPath + Constants.TRANSACTION_REPORT_DEST_FOLDER, "ebay_transaction_report_"
						+ CommonUtil.getDateString(yesterday) + "_" + CommonUtil.getDateString(todayDate) + ".txt");
				FileUtils.copyURLToFile(sourceWebSite, destFile, Constants.FILE_DOWNLOAD_CONNECTION_TIMEOUT, Constants.FILE_READ_TIMEOUT);
				reader = new InputStreamReader(new FileInputStream(destFile));
				readTabDelimitedFile4Ebay(destFile);
			} catch (IOException ioe) {
				logger.error("Error:Not able to get Daily Transaction file ", ioe);

			} finally {
				if (reader != null) {
					try {
						reader.close();
					} catch (Exception ex) {
						ex.printStackTrace();
					}

				}

			}

		} else if (affiliate.getName().equalsIgnoreCase(Constants.SKIMLINKS)) {
			InputStream inputStream = null;
			try {
				Date todayDate = CommonUtil.getESTDateWithoutTime(new Date());
				Date sevenDaysBefore = CommonUtil.addDay(todayDate, -7);
				Date tomorrow = CommonUtil.addDay(todayDate, 1);
				// skimlinks, only get transaction data for the past week. bcz it has more delays
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("startDate=2013-01-01",
						"startDate=" + CommonUtil.getDateStringyyyymmddDash(sevenDaysBefore));
				// end-date is not included in the result
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("endDate=2013-01-01",
						"endDate=" + CommonUtil.getDateStringyyyymmddDash(tomorrow));
				// get timestamp
				String iSO8601Date = CommonUtil.getISO8601Date(new Date());
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("{TIMESTAMP}", iSO8601Date);
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("{PUBKEY}", Constants.SKIMLINKS_PUBKEY);
				String authToken = EncryptionUtil.md5(iSO8601Date + Constants.SKIMLINKS_PRIKEY);
				tranReportWSEndPointTemplate = tranReportWSEndPointTemplate.replace("{AUTHTOKEN}", authToken);

				URL sourceWebSite = new URL(tranReportWSEndPointTemplate);
				URLConnection urlConn = sourceWebSite.openConnection();
				inputStream = urlConn.getInputStream();
				// TODO, need to check pagination
				populateSkimLinksTransactionReport(inputStream);
			} catch (IOException ioe) {
				logger.error("Error:Not able to get Daily Transaction file ", ioe);

			} finally {
				if (inputStream != null) {
					try {
						inputStream.close();
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * if the content already have image, then extract the path of that image and return back;
	 * 
	 * @param content
	 * @return
	 */
	public String getFirstPicture(String content) {
		String result = "";
		Pattern pattern = Pattern.compile("(?i)<img\\s+(.*?)src\\s*=\\s*[\"']([^\"]+)[\"']");
		Matcher matcher = pattern.matcher(content);
		if (matcher.find()) {
			result = matcher.group(2);
		}
		return result;

	}

	public void readTabDelimitedFile4Ebay(File file) throws FileNotFoundException {
		HeaderColumnNameTranslateMappingStrategy<EbayTransactionReportBean> strat = new HeaderColumnNameTranslateMappingStrategy<EbayTransactionReportBean>();
		strat.setType(EbayTransactionReportBean.class);
		String[] columns = new String[] { "eventDate", "postingDate", "EventType", "amount", "programId", "programName", "campaignId",
				"campaignName", "toolId", "toolName", "customerId", "clickTimeStamp", "ebayItemId", "ebayLeafCatetoryId", "ebayQuantitySold",
				"ebayTotalSaleAmount", "itemSiteId", "metaCategoryId", "uniqueTransactionId", "userFrequencyId", "earning", "trafficType", "itemName" }; // the
		Hashtable<String, String> table = new Hashtable<String, String>();
		table.put("Event Date", "eventDate");
		table.put("Posting Date", "postingDate");
		table.put("Event Type", "EventType");
		table.put("Amount", "amount");
		table.put("Program Id", "programId");
		table.put("Program Name", "programName");
		table.put("Tool Id", "toolId");
		table.put("Tool Name", "toolName");
		table.put("Custom Id", "customerId");
		table.put("Click Timestamp", "clickTimeStamp");
		table.put("eBay Item ID", "ebayItemId");
		table.put("eBay Leaf Category ID", "ebayLeafCatetoryId");
		table.put("eBay Quantity Sold", "ebayQuantitySold");
		table.put("eBay Total Sale Amount", "ebayTotalSaleAmount");
		table.put("Item Site ID", "itemSiteId");
		table.put("Meta Category ID", "metaCategoryId");
		table.put("Unique Transaction ID", "uniqueTransactionId");
		table.put("User Frequency ID", "userFrequencyId");
		table.put("Earnings", "earning");
		table.put("Traffic Type", "trafficType");
		table.put("Item Name", "itemName");
		strat.setColumnMapping(table);
		CsvToBean<EbayTransactionReportBean> csv = new CsvToBean<EbayTransactionReportBean>();
		CSVReader reader = new CSVReader(new FileReader(file), '\t', CSVParser.NULL_CHARACTER);
		List<EbayTransactionReportBean> tranReportlist = csv.parse(strat, reader);
		// populate it into transaction staging table
		// Store ebay = storeEjb.getStoreByDomain(Constants.EBAY_DOMAIN);
		/**
		 * debugging opencsv CSVReader reader2 = new CSVReader(new FileReader(file), '\t', '\''); String[] nextLine; try { while ((nextLine =
		 * reader2.readNext()) != null) { // nextLine[] is an array of values from the line System.out.println(nextLine[0] + "etc..."); } } catch
		 * (Exception ex) { ex.printStackTrace(); }
		 */
		String ebayTotalSaleAmount = "";
		for (EbayTransactionReportBean ebayTranBean : tranReportlist) {
			if (!StringUtil.isNullOrBlank(ebayTranBean.getEarning())
					&& !tranReportStagingEjb.checkExist(ebayTranBean.getUniqueTransactionId(), new BigDecimal(ebayTranBean.getEarning()))) {
				TransactionReportStaging tranReportStaging = new TransactionReportStaging();
				tranReportStaging.setTransactionId(ebayTranBean.getUniqueTransactionId());
				tranReportStaging.setAffiliateNetwork(Constants.EBAYPARTNERNETWORK);
				tranReportStaging.setCommissionAmount(new BigDecimal(ebayTranBean.getEarning()).setScale(2, BigDecimal.ROUND_HALF_UP));
				tranReportStaging.setItemId(ebayTranBean.getEbayItemId());
				tranReportStaging.setRecordStatus(RecordStatus.PENDING);
				ebayTotalSaleAmount = ebayTranBean.getEbayTotalSaleAmount();
				if (!StringUtil.isNullOrBlank(ebayTotalSaleAmount)) {
					tranReportStaging.setTransactionAmount(new BigDecimal(ebayTranBean.getEbayTotalSaleAmount())
							.setScale(2, BigDecimal.ROUND_HALF_UP));
				}
				tranReportStaging.setTransactionDate(CommonUtil.parseDateYYYYDashmmDashdd(ebayTranBean.getEventDate()));
				tranReportStaging.setItemName(ebayTranBean.getItemName());
				tranReportStaging.setTransactionUserId(ebayTranBean.getCustomerId());
				tranReportStaging.setAdvertiserId(Constants.EBAY_DOMAIN);
				tranReportStaging.setAdvertiserName(Constants.EBAY_DOMAIN);
				tranReportStagingEjb.create(tranReportStaging);
			}
		}

	}

	public void readTabDelimitedFile4Linkshare(File file) throws FileNotFoundException {
		ColumnPositionMappingStrategy<LinkshareTransactionReportBean> strat = new ColumnPositionMappingStrategy<LinkshareTransactionReportBean>();
		strat.setType(LinkshareTransactionReportBean.class);
		String[] columns = new String[] { "customerId", "advertiserId", "advertiser", "orderId", "tranDate", "tranTime", "sku", "salesAmount",
				"quantity", "commissions", "processDate", "processTime" }; // the
		strat.setColumnMapping(columns);
		CsvToBean<LinkshareTransactionReportBean> csv = new CsvToBean<LinkshareTransactionReportBean>();
		CSVReader reader = null;
		try {
			reader = new CSVReader(new FileReader(file), ',');
			List<LinkshareTransactionReportBean> tranReportlist = csv.parse(strat, reader);
			// populate it into transaction staging table
			boolean firstRow = true;
			for (LinkshareTransactionReportBean linkShareTranReport : tranReportlist) {
				if (firstRow) {
					firstRow = false;
					continue;
				}
				if (!StringUtil.isNullOrBlank(linkShareTranReport.getCommissions())
						&& !tranReportStagingEjb.checkExist(linkShareTranReport.getOrderId(), new BigDecimal(linkShareTranReport.getCommissions()),
								linkShareTranReport.getSku())) {
					TransactionReportStaging tranReportStaging = new TransactionReportStaging();
					tranReportStaging.setTransactionId(linkShareTranReport.getOrderId());
					tranReportStaging.setAffiliateNetwork(Constants.LINKSHARE);
					tranReportStaging.setCommissionAmount(new BigDecimal(linkShareTranReport.getCommissions()).setScale(2, BigDecimal.ROUND_HALF_UP));
					tranReportStaging.setItemId(linkShareTranReport.getSku());
					tranReportStaging.setItemName(linkShareTranReport.getSku());
					tranReportStaging.setRecordStatus(RecordStatus.PENDING);
					tranReportStaging
							.setTransactionAmount(new BigDecimal(linkShareTranReport.getSalesAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
					tranReportStaging.setTransactionDate(CommonUtil.parseDatemmddyyyyDash(linkShareTranReport.getTranDate()));
					tranReportStaging.setTransactionUserId(linkShareTranReport.getCustomerId());
					tranReportStaging.setAdvertiserId(linkShareTranReport.getAdvertiserId());
					tranReportStaging.setAdvertiserName(linkShareTranReport.getAdvertiser());
					tranReportStagingEjb.create(tranReportStaging);
				}
			}

		} catch (Exception ex) {
			logger.error("Error:Not able to parse CSV file ", ex);

		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (Exception ex) {
					ex.printStackTrace();
				}

			}

		}

	}

	public void populateCJTransactionReport(InputStream inputStream) {
		CJTransactionReports cjTransactionReports = null;
		if (inputStream == null) {
			return;
		}
		try {
			JAXBContext context = JAXBContext.newInstance(CJTransactionReports.class);
			// get variables from our xml file, created before
			Unmarshaller um = context.createUnmarshaller();
			cjTransactionReports = (CJTransactionReports) um.unmarshal(new StreamSource(inputStream));
		} catch (JAXBException jaxbExp) {
			jaxbExp.printStackTrace();
		}
		if (cjTransactionReports == null) {
			return;
		}
		ArrayList<CJTransactionReportBean> list = cjTransactionReports.getCjCommission().getTransactionRecord();
		if (list == null || list.isEmpty()) {
			return;
		}

		for (CJTransactionReportBean tranReportBean : list) {
			if (null == tranReportStagingEjb.getTransactionReportStaging(tranReportBean.getCommissionId())) {
				TransactionReportStaging tranReportStaging = new TransactionReportStaging();
				tranReportStaging.setTransactionId(tranReportBean.getCommissionId());
				tranReportStaging.setAffiliateNetwork(Constants.CJ);
				tranReportStaging.setCommissionAmount(new BigDecimal(tranReportBean.getCommissionAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
				tranReportStaging.setRecordStatus(RecordStatus.PENDING);
				tranReportStaging.setTransactionAmount(new BigDecimal(tranReportBean.getSalesAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
				tranReportStaging.setTransactionDate(CommonUtil.parseDateYYYYDashmmDashdd(tranReportBean.getEventDate()));
				// TODO critical, need to fix this once we get the file from
				// linkshare with customer id
				tranReportStaging.setTransactionUserId(tranReportBean.getSid());
				tranReportStaging.setAdvertiserId(tranReportBean.getCid());
				tranReportStaging.setAdvertiserName(tranReportBean.getAdvertiserName());
				tranReportStagingEjb.create(tranReportStaging);
			}

		}
	}

	public void populateSkimLinksTransactionReport(InputStream inputStream) {
		SkimLinksTransactionReports skimLinksTransactionReports = null;
		if (inputStream == null) {
			return;
		}
		try {
			JAXBContext context = JAXBContext.newInstance(SkimLinksTransactionReports.class);
			// get variables from our xml file, created before
			Unmarshaller um = context.createUnmarshaller();
			skimLinksTransactionReports = (SkimLinksTransactionReports) um.unmarshal(new StreamSource(inputStream));
		} catch (JAXBException jaxbExp) {
			jaxbExp.printStackTrace();
		}
		if (skimLinksTransactionReports == null) {
			return;
		}
		ArrayList<SkimLinksTransactionReportBean> list = skimLinksTransactionReports.getSkimLinksCommission().getTransactionRecord();
		if (list == null || list.isEmpty()) {
			return;
		}

		for (SkimLinksTransactionReportBean tranReportBean : list) {
			if (tranReportBean.getCommissionType().equalsIgnoreCase("sale")
					&& null == tranReportStagingEjb.getTransactionReportStaging(tranReportBean.getCommissionId())) {
				TransactionReportStaging tranReportStaging = new TransactionReportStaging();
				tranReportStaging.setTransactionId(tranReportBean.getCommissionId());
				tranReportStaging.setAffiliateNetwork(Constants.SKIMLINKS);
				tranReportStaging.setCommissionAmount(new BigDecimal(tranReportBean.getCommissionValue()).movePointLeft(2).setScale(2,
						BigDecimal.ROUND_HALF_UP));
				tranReportStaging.setRecordStatus(RecordStatus.PENDING);
				tranReportStaging.setTransactionAmount(new BigDecimal(tranReportBean.getOrderValue()).movePointLeft(2).setScale(2,
						BigDecimal.ROUND_HALF_UP));
				tranReportStaging.setTransactionDate(CommonUtil.parseDateYYYYDashmmDashdd(tranReportBean.getEventDate()));
				tranReportStaging.setTransactionUserId(tranReportBean.getCustomID());
				tranReportStaging.setAdvertiserId(tranReportBean.getMerchantID());
				tranReportStaging.setAdvertiserName(tranReportBean.getUrl());
				tranReportStagingEjb.create(tranReportStaging);
			}

		}

	}

	public void populatePepperJamTransactionReport(InputStream inputStream) {
		PepperJamTransaction pepperJamTransaction = null;
		if (inputStream == null) {
			return;
		}
		try {
			JAXBContext context = JAXBContext.newInstance(PepperJamTransaction.class);
			// get variables from our xml file, created before
			Unmarshaller um = context.createUnmarshaller();
			pepperJamTransaction = (PepperJamTransaction) um.unmarshal(new StreamSource(inputStream));
		} catch (JAXBException jaxbExp) {
			jaxbExp.printStackTrace();
		}
		if (pepperJamTransaction == null) {
			return;
		}
		ArrayList<PepperJamTransactionReportBean> list = pepperJamTransaction.getTransactionReportBeanList();
		if (list == null || list.isEmpty()) {
			return;
		}

		for (PepperJamTransactionReportBean tranReportBean : list) {
			if (!tranReportBean.isNull() && null == tranReportStagingEjb.getTransactionReportStaging(tranReportBean.getOrderId())) {
				TransactionReportStaging tranReportStaging = new TransactionReportStaging();
				tranReportStaging.setTransactionId(tranReportBean.getOrderId());
				tranReportStaging.setAffiliateNetwork(Constants.PEPPERJAM);
				tranReportStaging.setCommissionAmount(new BigDecimal(tranReportBean.getCommission()).setScale(2, BigDecimal.ROUND_HALF_UP));
				tranReportStaging.setRecordStatus(RecordStatus.PENDING);
				tranReportStaging.setTransactionAmount(new BigDecimal(tranReportBean.getTransactionAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
				tranReportStaging.setTransactionDate(CommonUtil.parseDateYYYYDashmmDashdd(tranReportBean.getTransactionDate()));
				tranReportStaging.setTransactionUserId(tranReportBean.getSid());
				tranReportStaging.setAdvertiserId(tranReportBean.getAdvertiserId());
				tranReportStaging.setAdvertiserName(tranReportBean.getAdvertiserName());
				tranReportStagingEjb.create(tranReportStaging);
			}

		}
	}

	@Schedule(dayOfMonth = "*", month = "*", year = "*", hour = "4", persistent = false)
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void populateCashBackHistory() {
		tranReportStagingEjb.populateCashBackHistory();
	}

	public static void main(String[] args) {

	}
}
